#include "Game.h"
#include "sceneMain.h"
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_mixer.h>

Game::Game()
{
}

Game::~Game()
{
}

void Game::init()
{
    FPS = 60;
    frameTime = 1000 / FPS;

    // SDL 初始化
    if(SDL_Init(SDL_INIT_EVERYTHING))
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL init failed! Error: %s", SDL_GetError());
        isRunning = false;
    }

    // 创建窗口
    window = SDL_CreateWindow("Shooter", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_SHOWN);
    if(!window)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL window creation failed! Error: %s", SDL_GetError());
        isRunning = false;
    }

    // 创建渲染器
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if(!renderer)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL renderer creation failed! Error: %s", SDL_GetError());
        isRunning = false;
    }

    if(IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG) != (IMG_INIT_PNG | IMG_INIT_JPG))
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL image init failed! Error: %s", IMG_GetError());
        isRunning = false;
    }

    // 初始化音效
    if(Mix_Init(MIX_INIT_MP3 | MIX_INIT_OGG) != (MIX_INIT_MP3 | MIX_INIT_OGG))
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL mixer init failed! Error: %s", IMG_GetError());
        isRunning = false;
    }

    // 打开音频设备
    if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048))
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL mixer open audio failed! Error: %s", IMG_GetError());
        isRunning = false;
    }

    // 设置音效 channel 数量
    Mix_AllocateChannels(32);

    // 设置音乐音量
    Mix_VolumeMusic(MIX_MAX_VOLUME / 4);
    Mix_Volume(-1, MIX_MAX_VOLUME / 8);

    // 初始化背景卷轴
    nearStar.texture = IMG_LoadTexture(renderer, R"(D:\CPP_GameLibrary\Shooter\assets\image\Stars-A.png)");
    SDL_QueryTexture(nearStar.texture, NULL, NULL, &nearStar.width, &nearStar.height);
    nearStar.width /= 4;
    nearStar.height /= 4;
    nearStar.speed = 20;

    farStar.texture = IMG_LoadTexture(renderer, R"(D:\CPP_GameLibrary\Shooter\assets\image\Stars-B.png)");
    SDL_QueryTexture(farStar.texture, NULL, NULL, &farStar.width, &farStar.height);
    farStar.width /= 2;
    farStar.height /= 2;
    farStar.speed = 10;
    
    // 初始化字体
    TTF_Init();

    currentScene = new SceneMain();
    currentScene->init();

    isRunning = true;
}   

void Game::run()
{
    while(isRunning)
    {
        Uint32 fameStartTime = SDL_GetTicks();

        SDL_Event event;
        handleEvent(&event);

        update(deltaTime);

        render();

        Uint32 fameEndTime = SDL_GetTicks();

        // 计算实际帧时间差
        Uint32 frameDiff = fameEndTime - fameStartTime;
        // 如果实际帧时间差小于锁定的帧时间，则等待剩余时间
        if(frameDiff < frameTime)
        {
            // 等待剩余时间
            SDL_Delay(frameTime - frameDiff);

            // 毫秒换算成秒
            deltaTime = frameTime / 1000.0f;
        }
        else
        {
            // 如果实际帧时间差大于等于锁定的帧时间，则使用实际帧时间差
            // 毫秒换算成秒
            deltaTime = frameDiff / 1000.0f;
        }
    }
}

void Game::clean()
{
    if(currentScene)
    {
        currentScene->clean();
        delete currentScene;
    }

    // 清理背景资源
    SDL_DestroyTexture(nearStar.texture);
    SDL_DestroyTexture(farStar.texture);

    // 清理音效
    Mix_CloseAudio();
    Mix_Quit();

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void Game::changeScene(SceneBase *scene)
{
    if(currentScene)
    {
        currentScene->clean();
        delete currentScene;
    }

    currentScene = scene;
    currentScene->init();
}

void Game::handleEvent(SDL_Event* event)
{
    while(SDL_PollEvent(event))
    {
        if(event->type == SDL_QUIT)
        {
            isRunning = false;
        }
        currentScene->handleEvent(event);
    }
}

void Game::update(float deltaTime)
{
    updateBackground(deltaTime);
    currentScene->update(deltaTime);
}

void Game::render()
{
    // 清空
    SDL_RenderClear(renderer);

    renderBackground();

    currentScene->render();

    // 显示更新
    SDL_RenderPresent(renderer);
}

void Game::updateBackground(float deltaTime)
{
    nearStar.offset += nearStar.speed * deltaTime;
    if(nearStar.offset >= 0)
    {
        nearStar.offset -= nearStar.height;
    }

    farStar.offset += farStar.speed * deltaTime;
    if(farStar.offset >= 0)
    {
        farStar.offset -= farStar.height;
    }
}

void Game::renderBackground()
{
    for(int posY = static_cast<int>(nearStar.offset); posY < getWindowHeight(); posY += nearStar.height)
    {
        for(int posX = 0; posX < getWindowWidth(); posX += nearStar.width)
        {
            SDL_Rect dstRect = {posX, posY, nearStar.width, nearStar.height};
            SDL_RenderCopy(renderer, nearStar.texture, NULL, &dstRect);
        }
    }

    for(int posY = static_cast<int>(farStar.offset); posY < getWindowHeight(); posY += farStar.height)
    {
        for(int posX = 0; posX < getWindowWidth(); posX += farStar.width)
        {
            SDL_Rect dstRect = {posX, posY, farStar.width, farStar.height};
            SDL_RenderCopy(renderer, farStar.texture, NULL, &dstRect);
        }
    }
}
